#include <stdio.h>

/* Parser States */
enum {
    BEGIN,
    IN_MEDIA,
    IN_WHITE_LINE,
    IN_COMMENT,
    IN_LABEL,
    IN_TIME_SECONDS,
    IN_TIME_FLAG,
    IN_TIME_1ST_SEGMENT,
    IN_TIME_2ND_SEGMENT,
    IN_TIME_3RD_SEGMENT,
    IN_TIME_COLON,
    END_OF_FILE
} ps ;


const int START = -1;
const int END = -2;

typedef struct {
    unsigned int hours;
    unsigned int minutes;
    unsigned int seconds;
    int flag;
} BingewatchTime;

/**
 * Set time from seconds.
 */
int bingewatch_time_set_seconds(BingewatchTime* self, 
                                const unsigned int seconds) {
    // Return error if result would be bigger than 99:59:59
    if (seconds > 359999)
        return 1;
    int rest_seconds, hours, minutes;
    self->hours = seconds / 3600;
    rest_seconds = seconds % 3600;
    self->minutes = rest_seconds / 60;
    self->seconds = rest_seconds % 60;
    return 0;
}

/**
 * Set hours minutes and seconds of the given Time-struct
 */
int bingewatch_time_set_hms(BingewatchTime* self, 
                            const unsigned int hours,
                            const unsigned int minutes,
                            const unsigned int seconds) {
    if (seconds > 59 || minutes > 59 || hours > 99)
        return 1;
    self->hours = hours;
    self->minutes = minutes;
    self->seconds = seconds;
    return 0;
}

/**
 * Check whether this time is the END-flag 
 */
int bingewatch_time_is_end(BingewatchTime* self) {
    return self->flag == END;
}

/**
 * Check whether this time is the START-flag 
 */
int bingewatch_time_is_start(BingewatchTime* self) {
    return self->flag == START
       || (self->hours == 0 && self->minutes == 0 && self->seconds == 0);
}

enum {
    INTRO,
    CREDITS,
    ADVERTISEMENT,
    MISC
} BingewatchLabel;

typedef struct {
    int label;
    BingewatchTime begin;
    BingewatchTime end;
} BingewatchPeriod;

typedef struct {
    char* medium;
    BingewatchPeriod** periods;
} BingewatchMedium;

/**
 * Returns 0 if the given period doesn't overlap with any of the already set periods
 * Returns > 0 if otherwise
 */
int bingewatch_medium_check_period_conflict(BingewatchMedium* self, BingewatchPeriod* period) {
    return 0;
}

/**
 * Add period to this medium
 */ 
int bingewatch_medium_add_period(BingewatchMedium* self, BingewatchPeriod* period) {
    if (bingewatch_medium_check_period_conflict(self, period))
        return 1;
    return 0;
}

/**
 * Remove period from this medium
 */
int bingewatch_medium_remove_period(BingewatchMedium* self, BingewatchPeriod* period) {
    return 0;
}

typedef struct {
    BingewatchMedium** media;
} BingewatchPlaylist;

/**
 * Parse the contents of a file into a BingewatchPlaylist struct and
 * return a pointer to the created struct
 */
BingewatchPlaylist* bingewatch_parse_file(char* path) {
    FILE* fd = fopen(path, "r");
    if (fd == NULL);
        return NULL;
    char c;
    short state = BEGIN;
    int line = 1;
    int col = 1;

    char* current_token;
    int current_token_size = 128;

    short expecting_unicode_byte = 0;
    while ((c = fgetc(fd)) != EOF) {
        switch (state) {
            case BEGIN:
                switch(c) {
                    case ' ':
                    case '\t':
                        state = IN_WHITE_LINE; break;
                    case '\n':
                        state = BEGIN; break;
                    case '#':
                        state = IN_COMMENT; break;
                    default:
                        state = IN_MEDIA; break;
                }
            case IN_COMMENT:
                switch(c) {
                    case '\n':
                        state = BEGIN; break;
                    default: break;
                }
            case IN_WHITE_LINE:
                switch(c) {
                    case ' ':
                    case '\t':
                        break;
                    case '\n':
                        state = BEGIN; break;
                    case 'I': case 'i':
                    case 'A': case 'a':
                    case 'O': case 'o':
                    case 'M': case 'm':
                        state = IN_LABEL; break;
                    default:
                        perror("invalid label");
                        break;
            }
        }
        if (c == '\n') {
            line++;
            col = 0;
        }
        col++;
        
    }
    fclose(fd);
}

void bingewatch_write_file(char* path) {
    FILE* fd = fopen(path, "w");
    fclose(fd);
}

int glib_parse(char* data, int error) {
    int state = BEGIN;
    char i = *data;
    for (;(char)i!='\0';i++) {
        switch (state) {
            case BEGIN:
                break;
        }
    }
}

